package com.zz.comframe.servlet;

/*
 * 创建日期 2006-7-23
 *
 * TODO 要更改此生成的文件的模板，请转至
 * 窗口 － 首选项 － Java － 代码样式 － 代码模板
 * 参数：
 * count:验证码的字符个数
 * width:验证码图片宽度
 * height:验证码图片高度
 * type:类型 0-纯数字 1-纯大写字母 2-数字和大学字母混合
 * 功能：生成验证码图片，将验证码保存进session里
 * 
 * 2010-9-9 增加功能，当参数param发来‘md5’时
 * 提供一个随机数，并保存入session，用于客户端md5加密时增加算子
 * 发来的md5码后从库中提取的密码加上session中的算子后再经md5后
 * 核对，一致则通过。
 */
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.zz.comframe.Validate_code;
import com.zz.comframe.properties.PropertiesPool;

public class ValidationCodeServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private final int TYPE_NUMBER = 0;

	private final int TYPE_LETTER = 1;
	//
	private final int TYPE_MULTIPLE = 2;

	private int width;

	private int height;

	private int count;

	private int type;

	private String validate_code;

	private Random random;

	private Font font;

	private int line;

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		width = 56;
		height = 22;
		count = 4;
		type = TYPE_NUMBER;
		random = new Random();
		line = 200;
	}

	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
		response.setContentType("image.jpeg");
		if(!PropertiesPool.CheckRequestParameters(request)){	
			//PrintWriter out = response.getWriter();
			//out.print("{\"success\":false,\"errors\":[{\"id\":\"checkcode\",\"msg\":\"请求中含有非法字符！\"}]}");			
			return;
		}

		String reqCount = request.getParameter("count");
		String reqWidth = request.getParameter("width");
		String reqHeight = request.getParameter("height");
		String reqType = request.getParameter("type");

		if (reqCount != null && reqCount != "")
			this.count = Integer.parseInt(reqCount);
		if (reqWidth != null && reqWidth != "")
			this.width = Integer.parseInt(reqWidth);
		if (reqHeight != null && reqHeight != "")
			this.height = Integer.parseInt(reqHeight);
		if (reqType != null && reqType != "")
			this.type = Integer.parseInt(reqType);

		font = new Font("Courier New", Font.BOLD, width / count);

		BufferedImage image = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);

		Graphics g = image.getGraphics();

		g.setColor(getRandColor(200, 250));
		g.fillRect(0, 0, width, height);

		g.setColor(getRandColor(160, 200));
		for (int i = 0; i < line; i++) {
			int x = random.nextInt(width);
			int y = random.nextInt(height);
			int xl = random.nextInt(12);
			int yl = random.nextInt(12);
			g.drawLine(x, y, x + xl, y + yl);
		}

		g.setFont(font);
		// validate_code = getValidateCode(count, type);
		HttpSession session = request.getSession();
		// .setAttribute("validate_code",validate_code);
		
		try {
			validate_code = Validate_code.makeValidate_code(count, type,
					session);	
		} catch (Exception e) {
			throw new NullPointerException("获取验证码出错");
		}
		
		for (int i = 0; i < count; i++) {
			g.setColor(new Color(20 + random.nextInt(110), 20 + random
					.nextInt(110), 20 + random.nextInt(110)));// 调用函数出来的颜色相同，可能是因为种子太接近，所以只能直接生成
			int x = (int) (width / count) * i;
			int y = (int) ((height + font.getSize()) / 2) - 5;
			g.drawString(String.valueOf(validate_code.charAt(i)), x, y);
		}

		g.dispose();
		//linux下未启动xwindow就无法显示    ImageIO.write(image, "JPEG", response.getOutputStream());
		//输出图象到页面 
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(response.getOutputStream());
		encoder.encode(image);

	}

	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		String param = request.getParameter("param");	//输出随机数，为密码md5加密增加算子
		if(!"md5".equals(param)){						//正常提供校验图片
			doGet(request, response);
		}else{									//提供md5算子
			response.setContentType("text/html; charset=utf-8");
			PrintWriter out = response.getWriter();
		if(!PropertiesPool.CheckRequestParameters(request)){	
			out.print("{\"success\":false,\"errors\":[{\"id\":\"checkcode\",\"msg\":\"请求中含有非法字符！\"}]}");			
			return;
		}
			
			HttpSession session = request.getSession();
			String md5oper = "";
			try {
				md5oper = Validate_code.makeMD5Operator(6, 0,session);	//产生6为数字型的随机数
			} catch (Exception e) {
				throw new NullPointerException("获取md5算子出错");
			}
			
			out.print("{\"success\":true,\"md5oper\":\"" + md5oper + "\"}");
		}
	}

	private Color getRandColor(int from, int to) {
		Random random = new Random();
		if (to > 255)
			from = 255;
		if (to > 255)
			to = 255;
		int rang = Math.abs(to - from);
		int r = from + random.nextInt(rang);
		int g = from + random.nextInt(rang);
		int b = from + random.nextInt(rang);
		return new Color(r, g, b);
	}

	/*
	 * private String getValidateCode(int size, int type) { StringBuffer
	 * validate_code = new StringBuffer(); for (int i = 0; i < size; i++) {
	 * validate_code.append(getOneChar(type)); } return
	 * validate_code.toString(); }
	 * 
	 * private String getOneChar(int type) { String result = null; switch (type) {
	 * case TYPE_NUMBER: result = String.valueOf(random.nextInt(10)); break;
	 * 
	 * case TYPE_LETTER: result = String.valueOf((char) (random.nextInt(26) +
	 * 65)); break;
	 * 
	 * case TYPE_MULTIPLE: if (random.nextBoolean()) { result =
	 * String.valueOf(random.nextInt(10)); } else { result =
	 * String.valueOf((char) (random.nextInt(26) + 65)); } break; default:
	 * result = null; break; } if (result == null) throw new
	 * NullPointerException("获取验证码出错"); return result; }
	 */
}
